package com.licq.ldoc;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.licq.ldoc.domain.Element;
import com.licq.ldoc.parser.impl.ElementParser;
import com.licq.ldoc.scanner.ClassProvider;
import com.licq.ldoc.utils.ClassUtils;
import com.licq.ldoc.writer.Writer;
import com.lowagie.text.DocumentException;

public class LDoc {
	private static transient Log logger = LogFactory.getLog(LDoc.class);
	
    private ClassProvider provider;
    
    private Predicate classPredicate = new DefaultClassPredicate();
    
    private Writer[] writers;

    public LDoc(ClassProvider provider, Writer writer) {
    	this(provider, new Writer[] {writer});
    }
    
    public LDoc(ClassProvider provider, Writer[] writers) {
    	this.provider = provider;
    	this.writers = writers;
    }

    @SuppressWarnings("unchecked")
	public void process() throws IOException, ClassNotFoundException, DocumentException {
        Collection<Class<?>> classes = CollectionUtils.select(provider.fetch(), classPredicate);
        if (classes.isEmpty()) {
        	if (logger.isInfoEnabled()) {
        		logger.info("there is no classes found by the provider.");
        	}
        	return;
        }
        List<Element> elements = new ArrayList<Element>();
        for (Class<?> clazz : classes) {
            Element element = ElementParser.parse(clazz);
            elements.add(element);
        }
        for (Writer writer : writers) {
        	writer.write(elements);
        }
    }

	public void setClassPredicate(Predicate classPredicate) {
		this.classPredicate = classPredicate;
	}
	
    class DefaultClassPredicate implements Predicate {
    	@Override
    	public boolean evaluate(Object object) {
    		return Class.class.isInstance(object) && !ClassUtils.isAbstractClass(((Class<?>) object));
    	}
    }
    
    /**
     * Usage: java LDoc [jarpaths...] classpatterns... outdir filename
     * @param args
     * @throws IOException
     * @throws ClassNotFoundException
     * @throws DocumentException
     */
    public static void main(String[] args) throws Exception {
        if (args.length != 4) {
            System.out.println("Usage: jarfile 'pattern1,pattern2',outpath,outfilename'");
        }
        LDocConsole.execute(args);
	}

}
